package com.song.boot.springstudy.netty.buf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.IllegalReferenceCountException;
import io.netty.util.ReferenceCountUtil;

public class ByteBufReferenceCountDemo {
    public static void main(String[] args) {
        // 1. 创建 ByteBuf 实例（Unpooled 是 Netty 提供的非池化缓冲区工具类）
        // 初始引用计数为 1
        ByteBuf buf = Unpooled.directBuffer(10); // 创建容量为 10 的缓冲区
        System.out.println("1. 初始状态 - 引用计数: " + buf.refCnt()); // 输出: 1

        // 2. 向缓冲区写入数据（模拟实际使用场景）
        buf.writeBytes("Netty Demo".getBytes());
        System.out.println("2. 写入数据后 - 缓冲区内容: " + buf.toString()); // 输出: Netty Demo

        // 3. 调用 retain() 增加引用计数（模拟多地方共享缓冲区）
        buf.retain();
        System.out.println("3. 调用 retain() 后 - 引用计数: " + buf.refCnt()); // 输出: 2

        // 4. 第一次调用 release() 减少引用计数
        boolean isReleasedFirst = buf.release();
        System.out.println("4. 第一次调用 release() - 引用计数: " + buf.refCnt() 
                + "，是否完全释放: " + isReleasedFirst); // 输出: 1，false

        // 5. 模拟缓冲区在另一处使用（再次调用 retain()）
        buf.retain();
        System.out.println("5. 再次调用 retain() 后 - 引用计数: " + buf.refCnt()); // 输出: 2

        // 6. 第二次调用 release() 减少引用计数
        boolean isReleasedSecond = buf.release();
        System.out.println("6. 第二次调用 release() - 引用计数: " + buf.refCnt() 
                + "，是否完全释放: " + isReleasedSecond); // 输出: 1，false

        // 7. 第三次调用 release()（此时计数将降为 0，底层内存回收）
        boolean isReleasedFinal = buf.release();
        System.out.println("7. 第三次调用 release() - 引用计数: " + buf.refCnt() 
                + "，是否完全释放: " + isReleasedFinal); // 输出: 0，true

        // 8. 注意：计数为 0 后，缓冲区已被回收，不可再使用（否则会抛异常）
        try {
            buf.writeByte(1); // 尝试操作已回收的缓冲区
        } catch (IllegalReferenceCountException e) {
            System.out.println("8. 操作已回收的缓冲区 - 异常: " + e.getClass().getSimpleName());
            System.out.println("   异常原因: 引用计数为 0，底层内存已释放，不可再操作");
        }
        System.out.println(buf.refCnt());

        // 9. 推荐用法：使用 ReferenceCountUtil 工具类安全释放（避免重复释放）
        ByteBuf safeBuf = Unpooled.buffer(5);
        System.out.println("9安全释放演示 - 初始引用计数: " + safeBuf.refCnt()); // 输出: 1
        ReferenceCountUtil.release(safeBuf); // 安全释放（内部会判断计数是否已为 0）
        // ReferenceCountUtil.release(safeBuf); // 重复释放不会抛异常（内部做了防护）
        System.out.println("9. 两次调用 ReferenceCountUtil.release() 后 - 引用计数: " + safeBuf.refCnt()); // 输出: 0
    }
}
    